// https://leetcode.cn/problems/minimum-genetic-mutation/description/

// 算法思路总结：
// 1. 广度优先搜索寻找基因突变的最短路径
// 2. 从起始基因开始，每次改变一个字符（A/C/G/T）
// 3. 只允许突变到银行中的有效基因序列
// 4. 使用哈希表记录访问状态，避免重复访问
// 5. 按层扩展，步数统计最短突变次数
// 6. 时间复杂度：O(32×n)，空间复杂度：O(n)

#include <iostream>
using namespace std;

#include <queue>
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_set>

class Solution 
{
public:
    int minMutation(string startGene, string endGene, vector<string>& bank) 
    {
        unordered_set<string> vis;
        unordered_set<string> vaild(bank.begin(), bank.end());
        const string change = "ACGT";

        if (startGene == endGene)  return 0;
        if (vaild.count(endGene) == 0) return -1;

        queue<string> q;
        q.push(startGene);
        vis.insert(startGene);

        int step = 0;
        while (!q.empty()) 
        {
            int sz = q.size();
            for (int i = 0 ; i < sz ; i++)
            {
                string front = q.front();
                q.pop();
                if (front == endGene) return step;
                for (int i = 0 ; i < 8 ; i++)
                {
                    string tmp = front;
                    for (int j = 0 ; j < 4 ; j++)
                    {
                        tmp[i] = change[j];
                        if (vaild.count(tmp) && vis.count(tmp) == 0)
                        {
                            q.push(tmp);
                            vis.insert(tmp);
                        }
                    }
                }
            }
            step++;
        }

        return -1;
    }
};

int main()
{
    string start1 = "AACCGGTT", end1 = "AACCGGTA";
    string start2 = "AACCGGTT", end2 = "AAACGGTA";
    vector<string> bank1 = {"AACCGGTA"}, bank2 = {"AACCGGTA","AACCGCTA","AAACGGTA"};

    Solution sol;

    cout << sol.minMutation(start1, end1, bank1) << endl;
    cout << sol.minMutation(start2, end2, bank2) << endl;

    return 0;
}